package engine

import (
	"context"
	"fmt"

	"gitcode.com/eteam/sae.git/storage"
	"gitcode.com/eteam/sae.git/types"
)

type TaskHandler interface {
	UpdateTaskStatus(newStatusItem *storage.TaskStatusDbItem) error

	ListMessage() ([]*storage.MessageInfoDbItem, error)
	AddMessage(messageItem *storage.MessageInfoDbItem) error

	ListArtifact() ([]*storage.ArtifactInfoDbItem, error)
	AddArtifact(artifactItem *storage.ArtifactInfoDbItem) error
	UpdateArtifact(artifactItem *storage.ArtifactInfoDbItem) error

	ListFormDefine() ([]*storage.FormDefineInfoDbItem, error)
	AddFormDefine(formDefineItem *storage.FormDefineInfoDbItem) error
	UpdateFormDefine(formDefineItem *storage.FormDefineInfoDbItem) error
}

type _TaskHandlerImpl struct {
	ctx           context.Context
	taskId        string
	storageHandle *storage.StorageHandle
}

func newTaskHandlerImpl(ctx context.Context, taskId string, storageHandle *storage.StorageHandle) TaskHandler {
	return &_TaskHandlerImpl{
		ctx:           ctx,
		taskId:        taskId,
		storageHandle: storageHandle,
	}
}

func (thl *_TaskHandlerImpl) UpdateTaskStatus(newStatusItem *storage.TaskStatusDbItem) error {
	if newStatusItem == nil {
		return fmt.Errorf("wrong param")
	}
	err := thl.storageHandle.TaskInfoDao.UpdateStatus(thl.ctx, thl.taskId, newStatusItem)
	if err != nil {
		return err
	}
	//发送通知
	err = thl.storageHandle.EventDao.Publish(thl.ctx, thl.taskId, &types.TaskStatusUpdateEvent{
		TaskId: thl.taskId,
		Status: types.TaskStatus{
			State:     newStatusItem.State,
			Message:   newStatusItem.Message.ToMessage(),
			TimeStamp: newStatusItem.TimeStamp,
		},
		Final: newStatusItem.State == types.TaskCompleted || newStatusItem.State == types.TaskCanceled || newStatusItem.State == types.TaskFailed || newStatusItem.State == types.TaskRejected,
		Kind:  types.TaskStatusUpdateObjectKind,
	})
	if err != nil {
		return err
	}
	return nil
}

func (thl *_TaskHandlerImpl) ListMessage() ([]*storage.MessageInfoDbItem, error) {
	return thl.storageHandle.MessageInfoDao.ListByTask(thl.ctx, []string{thl.taskId})
}

func (thl *_TaskHandlerImpl) AddMessage(messageItem *storage.MessageInfoDbItem) error {
	if messageItem == nil {
		return fmt.Errorf("wrong param")
	}
	messageItem.TaskId = thl.taskId
	err := thl.storageHandle.MessageInfoDao.Upsert(thl.ctx, messageItem)
	if err != nil {
		return err
	}
	//发送通知
	err = thl.storageHandle.EventDao.Publish(thl.ctx, thl.taskId, messageItem.ToMessage())
	if err != nil {
		return err
	}
	return nil
}

func (thl *_TaskHandlerImpl) ListArtifact() ([]*storage.ArtifactInfoDbItem, error) {
	return thl.storageHandle.ArtifactInfoDao.ListByTask(thl.ctx, []string{thl.taskId})
}

func (thl *_TaskHandlerImpl) AddArtifact(artifactItem *storage.ArtifactInfoDbItem) error {
	if artifactItem == nil {
		return fmt.Errorf("wrong param")
	}
	artifactItem.TaskId = thl.taskId
	err := thl.storageHandle.ArtifactInfoDao.Insert(thl.ctx, artifactItem)
	if err != nil {
		return err
	}
	// 发送通知
	err = thl.storageHandle.EventDao.Publish(thl.ctx, thl.taskId, &types.TaskArtifactUpdateEvent{
		TaskId:   thl.taskId,
		Artifact: *artifactItem.ToArtifact(),
		Kind:     types.TaskArtifactUpdateObjectKind,
	})
	if err != nil {
		return err
	}
	return nil
}

func (thl *_TaskHandlerImpl) UpdateArtifact(artifactItem *storage.ArtifactInfoDbItem) error {
	if artifactItem == nil {
		return fmt.Errorf("wrong param")
	}
	artifactItem.TaskId = thl.taskId
	err := thl.storageHandle.ArtifactInfoDao.Update(thl.ctx, artifactItem)
	if err != nil {
		return err
	}
	//发送通知
	err = thl.storageHandle.EventDao.Publish(thl.ctx, thl.taskId, &types.TaskArtifactUpdateEvent{
		TaskId:   thl.taskId,
		Artifact: *artifactItem.ToArtifact(),
		Kind:     types.TaskArtifactUpdateObjectKind,
	})
	if err != nil {
		return err
	}
	return nil
}

func (thl *_TaskHandlerImpl) ListFormDefine() ([]*storage.FormDefineInfoDbItem, error) {
	return thl.storageHandle.FormDefineInfoDao.ListByTask(thl.ctx, []string{thl.taskId})
}

func (thl *_TaskHandlerImpl) AddFormDefine(formDefineItem *storage.FormDefineInfoDbItem) error {
	if formDefineItem == nil {
		return fmt.Errorf("wrong param")
	}
	formDefineItem.TaskId = thl.taskId
	err := thl.storageHandle.FormDefineInfoDao.Insert(thl.ctx, formDefineItem)
	if err != nil {
		return err
	}
	//发送通知
	err = thl.storageHandle.EventDao.Publish(thl.ctx, thl.taskId, &types.TaskFormDefineUpdateEvent{
		TaskId:     thl.taskId,
		FormDefine: *formDefineItem.ToFormDefine(),
		Kind:       types.TaskFormDefineUpdateObjectKind,
	})
	if err != nil {
		return err
	}
	return nil
}

func (thl *_TaskHandlerImpl) UpdateFormDefine(formDefineItem *storage.FormDefineInfoDbItem) error {
	if formDefineItem == nil {
		return fmt.Errorf("wrong param")
	}
	formDefineItem.TaskId = thl.taskId
	err := thl.storageHandle.FormDefineInfoDao.Update(thl.ctx, formDefineItem)
	if err != nil {
		return err
	}
	//发送通知
	err = thl.storageHandle.EventDao.Publish(thl.ctx, thl.taskId, &types.TaskFormDefineUpdateEvent{
		TaskId:     thl.taskId,
		FormDefine: *formDefineItem.ToFormDefine(),
		Kind:       types.TaskFormDefineUpdateObjectKind,
	})
	if err != nil {
		return err
	}
	return nil
}
